(require 'eieio)

(defclass class ()
  ((name
   :initarg :name
   :documentation "class name")
   (path
   :initarg :path
   :documentation "as file location")
  (package
   :initarg :package
   :documentation "class's package")
  (imports
   :initarg :imports
   :initform '()
   :documentation "imported packaged")
  (variables
   :initarg :variables
   :initform '()
   :documentation "variables defined in the class.")
  (functions
   :initarg :functions
   :initform '()
   :documentation "functions defind in the class."))
  "a class infomation")


(defclass variable ()
  ((name 
    :initarg :name
    :reader name
    :documentation "variable name")
   (type 
    :initarg :type
    :reader type
    :documentation "type of the variable")
   (scope
    :initarg :scope
    :initform "private"))
  "variable infomation")

(defclass function ()
  ((name 
    :initarg :name
    :reader name
    :documentation "function name")
   (return-type
    :initarg :return-type
    :reader return-type
    :documentation "return type of the function")
   (parameters
    :initarg :parmaters
    :initform '()
    :reader paramters)
   (scope
    :initarg :scope
    :initform "public")))

(defclass parameter ()
  ((name 
    :initarg :name
    :reader name
    :documentation "parameter name")
   (type 
    :initarg :type
    :reader type
    :documentation "type of the parmeter"))
  "parameter infomation of function")

(defun add-function (function class)
  (let ((fun-list (oref class functions))
	(validate 't))
    ;;;check if parameter has unbound property
    (unless (and (slot-boundp variable :name)
		 (slot-boundp variable :type))
      (setq validate nil))
    (when validate
      (push function fun-list)
      (oset class functions fun-list))))


(defun add-variable (variable class)
  (let ((var-list (oref class variables))
	(contains nil)
	(validate 't))
    ;;;check if variable has unbound property
    (unless (and (slot-boundp variable :name)
		 (slot-boundp variable :type))
      (setq validate nil))
    (dolist (var var-list)
      (when (equal (oref variable name) (oref var name))
	(setq contains 't)))
    (when (and (not contains) validate) 
      (push variable var-list)
      (oset class variables var-list))))




(defun add-parameter (parameter function)
  (let ((para-list (oref function parameters))
	(validate 't))
    ;;;check if parameter has unbound property
    (unless (and (slot-boundp variable :name)
		 (slot-boundp variable :type))
      (setq validate nil))
    (when validate
      (push parameter para-list)
      (oset function parameters para-list))))


(provide 'class)